package org.ejb.stateless;


import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.persistence.EntityManager;
import javax.persistence.NonUniqueResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.ejb.api.UtilisateurInterface;
import org.ejb.entities.Address;
import org.ejb.entities.Annonce;
import org.ejb.entities.Item;
import org.ejb.entities.OrderLine;
import org.ejb.entities.OrderParFois;
import org.ejb.entities.Utilisateur;
import org.ejb.entities.ValidationException;

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

/**
 * This class is a facade for all customer services.
 */
@SuppressWarnings(value = "unchecked")
@TransactionAttribute(value = TransactionAttributeType.REQUIRED)
@Stateless(mappedName = "org.ejb.stateless.UtilisateurStateless@Remote", description = "Utilisateur stateless", name = "UtilisateurStateless")
public class UtilisateurStateless implements UtilisateurInterface{

    // ======================================
    // =             Attributs              =
    // ======================================
    @PersistenceContext
    private EntityManager em;

    private final String cname = this.getClass().getName();
    private Logger logger = Logger.getLogger("org.ejb.stateless");

    // ======================================
    // =          Methodes publiques        =
    // ======================================
    public Utilisateur authenticate(final String login, final String password) {
        final String mname = "authenticate";
        logger.entering(cname, mname, new Object[]{login, password});

        // On s'assure de la validite des paramatres
        if (login == null || "".equals(login))
            throw new ValidationException("Invalid login");

        Query query;
        Utilisateur customer=null;

        // On recherche l'objet a partir de son login
        query = em.createQuery("select OBJECT(u) from Utilisateur u where u.email=:login");
        query.setParameter("login", login);
        try{
            customer = (Utilisateur) query.getSingleResult();

        }catch(NonUniqueResultException e){
        	e.printStackTrace();
        }catch(ClassCastException e){
        	e.printStackTrace();
        }
        // Check if it's the right password
        logger.exiting(cname, mname, customer);
        if (customer != null)
        	if(customer.matchPassword(password))
        		return customer;
        	else
        		return null;
        else
        	return null;
    }

    public void createCustomer(Utilisateur customer, Address address) throws Exception{
        final String mname = "createCustomer";
        logger.entering(cname, mname, customer);

        // On s'assure de la validite des paramatres
        if (customer == null) throw new ValidationException("Customer object is null");
        if (address == null) throw new ValidationException("Address object is null");
        //address.setUtilisateur(customer);
        customer.setAddress(address);
        em.persist(address);
        em.persist(customer);
        em.flush();
        
        logger.exiting(cname, mname, customer);
        
    }
    
    public Utilisateur findCustomer(final Long customerId) {
        final String mname = "findCustomer";
        logger.entering(cname, mname, customerId);

        // On s'assure de la validite des paramatres
        if (customerId == null)
            throw new ValidationException("Invalid id");

        Utilisateur customer;

        // On recherche l'objet a partir de son identifiant
        customer = em.find(Utilisateur.class, customerId);

        logger.exiting(cname, mname, customer);
        return customer;
    }

    public void deleteCustomer(final Utilisateur customer) {
        final String mname = "deleteCustomer";
        logger.entering(cname, mname, customer);

        // On s'assure de la validite des paramatres
        if (customer == null)
            throw new ValidationException("Customer object is null");

        // On supprime l'objet de la base de donnees
        em.remove(em.merge(customer));

        logger.exiting(cname, mname);
    }

    public Utilisateur updateCustomer(final Utilisateur customer, final Address address) {
        final String mname = "updateCustomer";
        logger.entering(cname, mname, customer);

        // On s'assure de la validite des paramatres
        if (customer == null)
            throw new ValidationException("Customer object is null");

        customer.setAddress(address);

        // On modifie l'objet de la base de donnees
        em.merge(customer);
        em.flush();

        logger.exiting(cname, mname, customer);
        return customer;
    }

    public List<Utilisateur> findCustomersList() {
        final String mname = "findCustomers";
        logger.entering(cname, mname);

        Query query;
        List<Utilisateur> customers;

        // On modifie l'objet de la base de donnees
        query = em.createQuery("SELECT u FROM Utilisateur u");
        customers = query.getResultList();

        logger.exiting(cname, mname, customers.size());
        return customers;
    }

    /** ******************************************************************************************/
    /** Un annonce est cree par un utilisateur, on note utilisateur_id dans un colonne d'annonce */
    public void ajouteAnnonce(Utilisateur customer, Annonce annonce){
    	final String mname = "ajouterAnnonce";
        logger.entering(cname, mname, customer);
        
        // On s'assure de la validite des paramatres
        if (customer == null) throw new ValidationException("Customer object is null");
        if (annonce == null) throw new ValidationException("Annonce object is null");
        
        annonce.setUtilisateur(customer);
        em.persist(annonce);
        
        logger.exiting(cname, mname, customer);
    }    
   
//    /** ******************************************************************************************/
//    /** Un annonce est cree par un utilisateur, on note utilisateur_id dans un colonne d'annonce */
//    public void ajouteLocation(Utilisateur customer, Location location){
//    	final String mname = "ajouterLocation";
//        logger.entering(cname, mname, location);
//        
//        // On s'assure de la validite des paramatres
//        if (customer == null) throw new ValidationException("Customer object is null");
//        if (location == null) throw new ValidationException("Location object is null");
//        
//        location.setUtilisateur(customer);
//        em.persist(location);
//        
//        logger.exiting(cname, mname, location);    	
//    }
    
      /** **************************************************************************************/
      /** un order est cree par un utilisateur, on note utilisateur_id dans un colonne d'order */
//    public void commandeOrder(Utilisateur customer, OrderParFois orderParFois){
//  	  final String mname = "ajouterOrder";
//  	  logger.entering(cname, mname, orderParFois);
//      
//      	// On s'assure de la validite des paramatres
//      	if (customer == null) throw new ValidationException("Customer object is null");
//      	if (orderParFois == null) throw new ValidationException("Location object is null");
//      
//      	orderParFois.setUtilisateur(customer);
//      	em.persist(orderParFois);
//      
//      	logger.exiting(cname, mname, orderParFois);    	 
//    }

      // d'abord persister d'address, apres l'utilisateur ciliqer le panier pour il persiste l'utilisateur
//    public void ajouteOrderParFoisAddress(OrderParFois orderParFois, Address deliveryAddress){
//  	  final String mname = "ajouterOrderParFoisAddress";
//  	  logger.entering(cname, mname, orderParFois);
//      
//      	// On s'assure de la validite des paramatres
//      	if (orderParFois == null) throw new ValidationException("OrderParFois object is null");
//      	if (deliveryAddress == null) throw new ValidationException("DeliveryAddress object is null");
//      
//      	orderParFois.setDeliveryAddress(deliveryAddress);
//      	em.persist(deliveryAddress);
//      	em.persist(orderParFois);
//      	
//      	logger.exiting(cname, mname, orderParFois);    	 
//    }

      public void ajouteOrderParFois(Utilisateur customer, OrderParFois orderParFois, Address deliveryAddress){
    	  final String mname = "ajouterOrderParFois";
    	  logger.entering(cname, mname, orderParFois);
        
        	// On s'assure de la validite des paramatres
        	if (customer == null) throw new ValidationException("Customer object is null");
        	if (orderParFois == null) throw new ValidationException("OrderParFois object is null");
        	if (deliveryAddress == null) throw new ValidationException("DeliveryAddress object is null");
        
        	orderParFois.setUtilisateur(customer);
        	orderParFois.setDeliveryAddress(deliveryAddress);
        	em.persist(deliveryAddress);
        	//em.flush();
        	em.persist(orderParFois);
        	
        	logger.exiting(cname, mname, orderParFois);    	 
      }
      
      public OrderParFois findOrderParFois(Long id) {
          final String mname = "findCustomer";
          logger.entering(cname, mname, id);

          // On s'assure de la validite des paramatres
          if (id == null)
              throw new ValidationException("Invalid id");

          OrderParFois orderParFois;

          // On recherche l'objet a partir de son identifiant
          orderParFois = em.find(OrderParFois.class, id);

          logger.exiting(cname, mname, id);
          return orderParFois;
      }
      
      /** *************************** NOUVEAU ************************************* */ 
      public List<OrderParFois> findOrderParFoisList(Utilisateur customer) {
          final String mname = "findOrderParFoisList";
          logger.entering(cname, mname);

          Query query;
          List<OrderParFois> orderParFoisList = new ArrayList<OrderParFois>();

          // On modifie l'objet de la base de donnees
          query = em.createQuery("SELECT orderParFois FROM OrderParFois AS orderParFois WHERE orderParFois.utilisateur.id=" + customer.getId());
          orderParFoisList = query.getResultList();

          logger.exiting(cname, mname, orderParFoisList.size());
          return orderParFoisList;
      }
      /** *************************** NOUVEAU ************************************* */ 
      
     public void ajouteOrderLine(OrderParFois orderParFois, OrderLine orderLine){
	    	final String mname = "ajouterOrderLine";
	    	logger.entering(cname, mname, orderLine);
        
        	// On s'assure de la validite des paramatres
        	if (orderParFois == null) throw new ValidationException("OrderParFois object is null");
        	if (orderLine == null) throw new ValidationException("OrderLine object is null");
        
        	orderLine.setOrderParFois(orderParFois);
        	em.persist(orderLine);
        	
        	logger.exiting(cname, mname, orderLine);
	 }
     
     public OrderLine findOrderLine(Long id) {
         final String mname = "findCustomer";
         logger.entering(cname, mname, id);

         // On s'assure de la validite des paramatres
         if (id == null)
             throw new ValidationException("Invalid id");

         OrderLine orderLine;

         // On recherche l'objet a partir de son identifiant
         orderLine = em.find(OrderLine.class, id);

         logger.exiting(cname, mname, id);
         return orderLine;
     }
     
     /** *************************** NOUVEAU ************************************* */ 
     public List<OrderLine> findOrderLineList(OrderParFois orderParFois) {
         final String mname = "findOrderParLineList";
         logger.entering(cname, mname);

         Query query;
         List<OrderLine> orderParLineList  = new ArrayList<OrderLine>();

         // On modifie l'objet de la base de donnees
         query = em.createQuery("SELECT orderLine FROM OrderLine AS orderLine WHERE orderLine.orderParFois.id=" + orderParFois.getId());
         orderParLineList = query.getResultList();

         logger.exiting(cname, mname, orderParLineList.size());
         return orderParLineList;
     }
     /** *************************** NOUVEAU ************************************* */ 
     
     public void ajouteOrderLineItem(OrderLine orderLine, Item item){
   	  final String mname = "ajouterOrderLine";
   	  logger.entering(cname, mname, orderLine);
       
       	// On s'assure de la validite des paramatres
       	if (orderLine == null) throw new ValidationException("OrderLine object is null");
       	if (item == null) throw new ValidationException("Item object is null");
       
       	orderLine.setItem(item);
       	em.merge(orderLine);
       	
       	logger.exiting(cname, mname, orderLine);    	 
     }

}
